package org.iku.index;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.FSDirectory;
import org.iku.common.ActressTool;
import org.iku.common.BasicIndexBuilder;
import org.iku.common.CategoryTool;
import org.iku.common.CommonTool;
import org.iku.common.FieldOption;
import org.iku.dao.ItemIndexDAO;
import org.iku.entity.Actress;
import org.iku.entity.Category;
import org.iku.entity.IndexHistory;
import org.iku.entity.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.google.gson.Gson;

@Component
public class ItemIndexBuilder extends BasicIndexBuilder{
	private Logger logger = Logger.getLogger(ItemIndexBuilder.class);

	@Value("#{settings['item.update.limit']}")
	private int limit;
	@Value("#{settings['item.index.rebuild']}")
	private boolean rebuild;
	private File file;
	@Value("#{settings['item.index.path']}")
	private String path;
	
	@Autowired
	private IndexWriterConfig itemIndexWriterConfig;
	@Autowired
	private ItemIndexDAO itemIndexDAO;
	
	private FSDirectory directory;
	private IndexWriter writer;
	
	@PostConstruct
	public void init(){
		FieldOption.init();
		CategoryTool.init(itemIndexDAO);
		ActressTool.init(itemIndexDAO);
		file = new File(path);
		if(rebuild){
			if(file.isDirectory()){
				for(File child : file.listFiles()){
					child.delete();
				}
			}
		}
	}
	
	@Override
	@Scheduled(cron="0 0/3 * * * *")
	public void build(){
			IndexHistory indexHistory = itemIndexDAO.getLastDate(rebuild,0);
			writer = init(itemIndexWriterConfig,directory,file);
			Date lastDate = indexHistory.getDate();
			Date date = Calendar.getInstance().getTime();
			int index = 0;
			int add = 0;
			int update = 0;
			try {
				//获取增量数据信息
				List<Item> items = itemIndexDAO.fetchIncreaseData(index,limit,lastDate);
				while(null != items && items.size()>0){
//			long start = Calendar.getInstance().getTimeInMillis();
					for(Item item : items){
						Date createTime = item.getCreateTime();
						Document document = injector(item);
						if(lastDate.before(createTime)){//最后一次索引时间早于该记录创建时间,属于新增记录
							addIndex(document);
							add+=1;
						}else{//最后一次索引时间晚于该记录创建时间,属于更新记录
//							System.out.println("update goods_id:"+map.get("GOODS_ID"));
							updateIndex("id",document);
							update+=1;
						}
					}
					index+=limit;
//			long end = Calendar.getInstance().getTimeInMillis();
					items = itemIndexDAO.fetchIncreaseData(index,limit,lastDate);
//			long sqlend = Calendar.getInstance().getTimeInMillis();
//			logger.info("idx time："+(end-start)+"ms;sql time:"+(sqlend-end)+"ms");
//			logger.info("========================================");
				}
				
				if(add!=0 || update!=0){
					writer.commit();
					writer.optimize();
					logger.info("本次新增item条数："+add);
					logger.info("本次更新item条数："+update);
				}
			} catch (Exception e) {
				logger.info(e.getMessage());
			}finally{
				rebuild = false;
				try {
					writer.close();
					if(IndexWriter.isLocked(directory)){
						IndexWriter.unlock(directory);
					}
					directory.close();
				} catch (Exception e2) {
					logger.info(e2.getMessage());
				}
			}
			itemIndexDAO.markDownLastDate(date,0);
	}

	private static Document injector(Item item){
		Document doc = new Document();
		
		Field id = new Field("id",String.valueOf(item.getId()),Store.YES,Index.NOT_ANALYZED);
		doc.add(id);
		
		Field sn = new Field("sn",String.valueOf(item.getSn()),Store.YES,Index.ANALYZED);
		doc.add(sn);
		
		Field titleCn = new Field("titleCn",item.getTitleCn(),Store.YES,Index.ANALYZED);
		doc.add(titleCn);
		
		
		Field titleEn = new Field("titleEn",item.getTitleEn(),Store.YES,Index.ANALYZED);
		doc.add(titleEn);
		
		
		Gson gson = new Gson();
		
		String actressIds = item.getActressIds();
		if(null != actressIds && !actressIds.isEmpty()){
			Integer[] actress = gson.fromJson(actressIds, Integer[].class);
			List<String> actsCn = new ArrayList<String>();
			List<String> actsEn = new ArrayList<String>();
			for(Integer aid : actress){
				Actress act = ActressTool.getActress(aid);
				String nameCn = act.getNameCn();
				actsCn.add(nameCn);
				String nameEn = act.getNameEn();
				actsEn.add(nameEn);
			}
			String nameCn = StringUtils.join(actsCn, "##");
			Field actressCn = new Field("actressCn", nameCn,Store.YES,Index.ANALYZED);
			doc.add(actressCn);
			String nameEn = StringUtils.join(actsEn, "##");
			Field actressEn = new Field("actressEn", nameEn,Store.YES,Index.ANALYZED);
			doc.add(actressEn);
		}
		
		
		String categoryIds = item.getCategory();
		if(null != categoryIds && !categoryIds.isEmpty()){
			Integer[] category = gson.fromJson(categoryIds, Integer[].class);
			List<String> catsCn = new ArrayList<String>();
			List<String> catsEn = new ArrayList<String>();
			for(Integer cid : category){
				Category cat = CategoryTool.getCategory(cid);
				String catCn = cat.getNameCn();
				catsCn.add(catCn);
				String catEn = cat.getNameEn();
				catsEn.add(catEn);
			}
			String catNameCn = StringUtils.join(catsCn, "##");
			Field categoryCn = new Field("categoryCn", catNameCn,Store.YES,Index.ANALYZED);
			doc.add(categoryCn);
			String catNameEn = StringUtils.join(catsEn, "##");
			Field categoryEn = new Field("categoryEn", catNameEn,Store.YES,Index.ANALYZED);
			doc.add(categoryEn);
		}
		
		return doc;
	}

	protected void addIndex(Document document){
		try {
			writer.addDocument(document);
		} catch (CorruptIndexException e) {
			logger.info(e.getMessage());
		} catch (IOException e) {
			logger.info(e.getMessage());
		}
	}
	
	protected void updateIndex(String primaryField,Document document){
		Term term = new Term(primaryField,document.get(primaryField));
		try {
			writer.updateDocument(term, document,itemIndexWriterConfig.getAnalyzer());
			writer.deleteUnusedFiles();
		} catch (CorruptIndexException e) {
			logger.info(e.getMessage());
		} catch (IOException e) {
			logger.info(e.getMessage());
		}
	}

	public static void main(String[] args) {
		Integer[] num = {1,3,4,5,7};
		Gson gson = new Gson();
		System.out.println(gson.toJson(num));
		Integer[] num1 = gson.fromJson(gson.toJson(num), Integer[].class);
		System.out.println(num1[1]);
	}
	
}